<?php
namespace app\controllers;

use yii\helpers\Url;
use yii\web\Controller;
use yii\db\Query;
use Yii;

class ExtensionController extends BaseController
{
    /**
     * 分机管理
     * @return string|\yii\web\Response
     */
    public function actionIndex()
    {
        if (Yii::$app->request->isAjax){
            $where = [
                'sip.keyword'=>'secret',
            ];
            $db = (new Query())->select(['users.extension','users.name','sip.data as secret'])
                ->from('users')
                ->join('left join','sip','users.extension=sip.id');
            $name = Yii::$app->request->get('name');
            if ($name){
                $where['users.name'] = $name;
            }
            $extension = Yii::$app->request->get('extension');
            if ($extension){
                $where['users.extension'] = $extension;
            }
            $db->where($where);
            $count = $db->count('users.extension',$this->asterisk_db);

            $page = Yii::$app->request->get('page',1);
            $limit = Yii::$app->request->get('limit',10);
            $data = $db->offset(($page-1)*$limit)->limit($limit)->all($this->asterisk_db);
            foreach ($data as &$d){
                $d['edit_url'] = Url::to(['edit','extension'=>$d['extension']]);
                $d['destroy_url'] = Url::to(['destroy','extension'=>$d['extension']]);
            }
            return $this->asJson([
                'code' => 0,
                'msg' => '请求成功',
                'count' => $count,
                'data' => $data
            ]);
        }
        return $this->render('index');
    }

    /**
     * 添加分机
     * @return string|\yii\web\Response
     */
    public function actionCreate()
    {
        //防止超时
        set_time_limit(0);
        if (Yii::$app->request->isPost){
            $type = Yii::$app->request->post('type');
            if ($type==1){
                $data = [
                    'from'      => Yii::$app->request->post('extension'),
                    'to'        => Yii::$app->request->post('extension'),
                    'name'      => Yii::$app->request->post('name'),
                    'secret'    => Yii::$app->request->post('secret'),
                ];
            }else{
                $data = [
                    'from'      => Yii::$app->request->post('extension_start'),
                    'to'        => Yii::$app->request->post('extension_end'),
                    'name'      => null,
                    'secret'    => Yii::$app->request->post('secret'),
                ];
            }

            //添加分机
            $transaction = $this->asterisk_db->beginTransaction();
            try{
                for ($exten = $data['from']; $exten <= $data['to']; $exten++){
                    $name = $data['name']?$data['name']:$exten;
                    $this->usersSipDevices($exten,$data['secret'],$name,'create');
                    $this->amiDb($exten,'create');
                }
                $transaction->commit();
                //必需在提交事务后才重启
                $this->reload();
                return $this->asJson(['code'=>0,'msg'=>'添加分机成功']);
            }catch (\Exception $exception){
                $transaction->rollBack();
                return $this->asJson(['code'=>1,'msg'=>'添加分机失败','data'=>$exception->getMessage()]);
            }

        }
        return $this->render('create');
    }

    public function actionEdit()
    {
        $exten = Yii::$app->request->get('extension');
        if (Yii::$app->request->isPost){
            $data = [
                'from'      => $exten,
                'to'        => $exten,
                'name'      => Yii::$app->request->post('name'),
                'secret'    => Yii::$app->request->post('secret'),
            ];
            //添加分机
            $transaction = $this->asterisk_db->beginTransaction();
            try{
                for ($exten = $data['from']; $exten <= $data['to']; $exten++){
                    $name = $data['name']?$data['name']:$exten;
                    $this->usersSipDevices($exten,$data['secret'],$name,'update');
                    $this->amiDb($exten,'create');
                }
                $transaction->commit();
                //必需在提交事务后才重启
                $this->reload();
                return $this->asJson(['code'=>0,'msg'=>'更新分机成功']);
            }catch (\Exception $exception){
                $transaction->rollBack();
                return $this->asJson(['code'=>1,'msg'=>'更新分机失败','data'=>$exception->getMessage()]);
            }
        }
        $extension = (new Query())->select(['users.extension','users.name','sip.data as secret'])
            ->from('users')
            ->join('left join','sip','users.extension=sip.id')
            ->where(['sip.keyword'=>'secret','users.extension'=>$exten])
            ->one($this->asterisk_db);
        return $this->render('edit',['extension'=>$extension]);
    }

    /**
     * 删除分机
     * @return string|\yii\web\Response
     */
    public function actionDestroy()
    {
        if (Yii::$app->request->isPost){
            $type = Yii::$app->request->post('type');
            if ($type==1){
                $data = [
                    'from'      => Yii::$app->request->post('extension'),
                    'to'        => Yii::$app->request->post('extension'),
                ];
            }else{
                $data = [
                    'from'      => Yii::$app->request->post('extension_start'),
                    'to'        => Yii::$app->request->post('extension_end'),
                ];
            }
            //删除分机
            $transaction = $this->asterisk_db->beginTransaction();
            try{
                for ($exten = $data['from']; $exten <= $data['to']; $exten++){
                    $this->usersSipDevices($exten,null,null,'destroy');
                    $this->removeFromQueue($exten);
                    $this->amiDb($exten,'destroy');
                }
                $transaction->commit();
                //必需在提交事务后才重启
                $this->reload();
                return $this->asJson(['code'=>0,'msg'=>'删除分机成功']);
            }catch (\Exception $exception){
                $transaction->rollBack();
                return $this->asJson(['code'=>1,'msg'=>'删除分机失败','data'=>$exception->getMessage()]);
            }
        }
        return $this->render('destroy');
    }

    private function amiDb($EXTEN,$ACTION) {
        $amidb = array(
            "AMPUSER/$EXTEN:answermode:disabled",
            "AMPUSER/$EXTEN:cfringtimer:0",
            "AMPUSER/$EXTEN:cidname:$EXTEN",
            "AMPUSER/$EXTEN:cidnum:$EXTEN",
            "AMPUSER/$EXTEN:concurrency_limit:0",
            "AMPUSER/$EXTEN:device:$EXTEN",
            "AMPUSER/$EXTEN:language:",
            "AMPUSER/$EXTEN:noanswer:",
            "AMPUSER/$EXTEN:outboundcid:",
            "AMPUSER/$EXTEN:password:",
            "AMPUSER/$EXTEN:queues/qnostate:usestate",
            "AMPUSER/$EXTEN:recording:",
            "AMPUSER/$EXTEN:recording/in/external:always",
            "AMPUSER/$EXTEN:recording/in/internal:always",
            "AMPUSER/$EXTEN:recording/ondemand:enabled",
            "AMPUSER/$EXTEN:recording/out/external:always",
            "AMPUSER/$EXTEN:recording/out/internal:always",
            "AMPUSER/$EXTEN:recording/priority:0",
            "AMPUSER/$EXTEN:ringtimer:30",
            "AMPUSER/$EXTEN:voicemail:novm",
            "CW:$EXTEN:ENABLED",
            "CALLTRACE:$EXTEN:$EXTEN",
            "DEVICE/$EXTEN:default_user:$EXTEN",
            "DEVICE/$EXTEN:dial:SIP/$EXTEN",
            "DEVICE/$EXTEN:type:fixed",
            "DEVICE/$EXTEN:user:$EXTEN"
        );
        foreach($amidb as &$valor) {
            list ($family,$key,$value) = preg_split("/:/",$valor,3);
            if ($ACTION=='create'){
                $this->ami->DatabasePut($family,$key,$value);
            }elseif ($ACTION=='destroy'){
                $this->ami->DatabaseDel($family,$key);
            }

        }
    }

    private function usersSipDevices($EXTEN,$SECRET,$NAME,$ACTION)
    {
        $sipset = array(
            array("secret",      "$SECRET",          2),
            array("dtmfmode",    "rfc2833",          3),
            array("canreinvite", "no",               4),
            array("context",     "from-internal",    5),
            array("host",        "dynamic",          6),
            array("trustrpid",   "yes",              7),
            array("sendrpid",    "no",               8),
            array("type",        "friend",           9),
            array("nat",         "yes",             10),
            array("port",        "5060",            11),
            array("qualify",     "yes",             12),
            array("qualifyfreq", "60",              13),
            array("transport",   "udp",             14),
            array("avpf",        "no",              15),
            array("force_avp",   "no",              16),
            array("icesupport",  "no",              17),
            array("dtlsenable",  "no",              18),
            array("dtlsverify",  "no",              19),
            array("dtlssetup",   "actpass",         20),
            array("encryption",  "no",              21),
            array("callgroup",   "",                22),
            array("pickupgroup", "",                23),
            array("disallow",    "",                24),
            array("allow",       "",                25),
            array("dial",        "SIP/$EXTEN",      26),
            array("accountcode", "",                27),
            array("mailbox",     "$EXTEN@device",   28),
            array("deny",        "0.0.0.0/0.0.0.0", 29),
            array("permit",      "0.0.0.0/0.0.0.0", 30),
            array("account",     "$EXTEN",          31),
            array("callerid",    "device <$EXTEN>", 32)
        );
        if ($ACTION=='create'){
            //写入sip表
            foreach($sipset as &$valor) {
                $this->asterisk_db->createCommand()->insert('sip',[
                    'id'=>$EXTEN,
                    'keyword'=>$valor[0],
                    'data'=>$valor[1],
                    'flags'=>$valor[2]
                ])->execute();
            }
            //写入users表
            $this->asterisk_db->createCommand()->insert('users',[
                'extension'=>$EXTEN,
                'password'=>'',
                'name'=>$NAME,
                'voicemail'=>'novm',
                'ringtimer'=>0,
                'noanswer'=>'',
                'recording'=>'',
                'outboundcid'=>'',
                'sipname'=>'',
                'mohclass'=>'default',
                'noanswer_cid'=>'',
            ])->execute();
            //写入devices
            $this->asterisk_db->createCommand()->insert('devices',[
                'id'=>$EXTEN,
                'tech'=>'sip',
                'dial'=>'SIP/'.$EXTEN,
                'devicetype'=>'fixed',
                'user'=>$EXTEN,
                'description'=>$NAME,
                'emergency_cid'=>''
            ])->execute();

        }elseif ($ACTION=='update'){
            //更新sip表
            foreach($sipset as &$valor) {
                $this->asterisk_db->createCommand()->update('sip',[
                    'data'=>$valor[1],
                    'flags'=>$valor[2]
                ],['id'=>$EXTEN,'keyword'=>$valor[0]])->execute();
            }
            //更新users表
            $this->asterisk_db->createCommand()->update('users',[
                'name'=>$NAME,
                'voicemail'=>'novm',
                'ringtimer'=>0,
                'mohclass'=>'default'
            ],['extension'=>$EXTEN])->execute();
            //写入devices
            $this->asterisk_db->createCommand()->update('devices',[
                'tech'=>'sip',
                'dial'=>'SIP/'.$EXTEN,
                'devicetype'=>'fixed',
                'user'=>$EXTEN,
                'description'=>$NAME
            ],['id'=>$EXTEN])->execute();
        }elseif ($ACTION=='destroy'){
            $this->asterisk_db->createCommand()->delete('sip',['id'=>$EXTEN])->execute();
            $this->asterisk_db->createCommand()->delete('users',['extension'=>$EXTEN])->execute();
            $this->asterisk_db->createCommand()->delete('devices',['id'=>$EXTEN])->execute();
            //删除队列里的该分机
            $this->asterisk_db->createCommand()->delete('queues_details',['data'=>'Local/'.$EXTEN.'@from-queue/n,0'])->execute();
        }
    }

    private function removeFromQueue($exten)
    {
        $this->asterisk_db->createCommand()->delete('queues_details',[
            'keyword' => 'member',
            'data' => 'Local/'.$exten.'@from-queue/n,0'
        ])->execute();
    }

}